package cn.edu.lingnan.service.impl;

import cn.edu.lingnan.context.BaseContext;
import cn.edu.lingnan.mapper.*;
import cn.edu.lingnan.service.ExamService;
import cn.edu.lingnan.user.dtos.*;
import cn.edu.lingnan.user.pojos.Exam;
import cn.edu.lingnan.user.pojos.PageBean;
import cn.edu.lingnan.user.pojos.User;
import cn.edu.lingnan.user.vos.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
@Slf4j
public class ExamServiceImpl implements ExamService {
    @Autowired
     private ExamMapper examMapper;

    @Autowired
    private PaperMapper paperMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private NotificationService notificationService;


    @Autowired
    private UserExamMapper userExamMapper;

    @Autowired
    private ClassMapper classMapper;

    @Override
    public PageBean<Exam> getExamList(ListExamDto listExamDto) {
        Integer userId = BaseContext.getCurrentId();
        // 查询用户角色类型
        Integer type = userMapper.getUserTypeByUserId(userId);

        // 设置当前用户id到 DTO 中
        listExamDto.setUserId(userId);

        // 启动分页
        PageHelper.startPage(listExamDto.getPage(), listExamDto.getSize());

        Page<Exam> page;

        if (type != null && type.equals(2)) { // 学生角色
            // 学生只能查看自己参加的考试
            page = examMapper.getMyExamList(listExamDto);
        } else { // 管理员或其他角色
            // 管理员可以查看所有考试
            page = examMapper.getExamList(listExamDto);
        }

        return new PageBean<>(page.getTotal(), page.getResult());
    }

    @Override
    public void addExam(Exam exam) {
        // 统一设置为当前分钟的00秒
        exam.setStartTime(exam.getStartTime().withSecond(0).plusHours(8));
        exam.setEndTime(exam.getEndTime().withSecond(0).plusHours(8));

        // 设置用户ID
        exam.setUserId(BaseContext.getCurrentId());

        // 调用mapper保存
        examMapper.addExam(exam);
    }

    @Override
    @Transactional
    public Integer deleteExam(Integer examId) {
        //正在考试的考试不能删除
      Integer status=  examMapper.getExamStatus(examId);
      if(status==2){
          return 0;
      }
      //已经存在考生的考试不能删除
        Integer count=  examMapper.getExamCount(examId);

        if(count>0&&status==3 ){
            return -1;
        }
        if(count>0&&status==1){
            return -2;
        }

        //再删除考试表中的记录
        examMapper.deleteExam(examId);
        return 1;
    }

    @Override
    public PageBean<?> getExamUser(ListUserExam listUserExam) {
        //查询考生状态
        PageHelper.startPage(listUserExam.getPage(), listUserExam.getSize());
        // 设置当前用户id
        Page<UserVO> page=examMapper.getExamUser(listUserExam);
        for(UserVO userVO:page.getResult()){
            Integer status=  examMapper.getExamUserStatus(userVO.getUserId(),listUserExam.getExamId());
              if(status!=null){
                  userVO.setStatus(status);

              }
        }
        return new PageBean<>(page.getTotal(),page.getResult());
    }

    @Override
    public Exam getExamById(Integer examId) {
        Exam exam = examMapper.getExamById(examId);
        //查询试卷名称
        String paperName=paperMapper.getPaperById(exam.getPaperId()).getPaperName();
        exam.setPaperName(paperName);
        //查询考生信息
        List<User> userList=userMapper.getUserByExamId(examId);
     exam.setUserList(userList);
        return exam;
    }


    @Override
    public void updateExam(Exam exam) {
        exam.setStartTime(exam.getStartTime().plusHours(8));
        exam.setEndTime(exam.getEndTime().plusHours(8));
        examMapper.updateExam(exam);
    }

    /**
     * 添加考试考生
     * @param addExamUserDto 包含考试ID和用户ID列表
     * @return 操作标志
     */
    @Override
    @Transactional
    public Integer addExamUser(AddExamUserDto addExamUserDto) {
        // 查询考试信息，确保考试数据有效
        Exam exam = examMapper.getExamById(addExamUserDto.getExamId());
        if (exam == null) {
            return -3; // 考试不存在
        }

        if (exam.getEndTime().isBefore(exam.getStartTime())) {
            return -1; // 截止时间不能早于开始时间
        }
        if (exam.getStatus() != 0) {
            return 0; // 考试不处于未发布状态
        }
        if (exam.getEndTime().isBefore(LocalDateTime.now()) || exam.getStartTime().isBefore(LocalDateTime.now())) {
            return -2; // 考试时间有误，请检查
        }
        // 查询考试是否已经存在考生
         List<Integer> userIds;
        //插入考生 通过直接添加学生的方式：使用场景：补考等
        if(addExamUserDto.getClassId()==null){
            userIds=addExamUserDto.getUserIds();
            for(Integer userId:userIds ){
                examMapper.addUserExam(userId,addExamUserDto.getExamId());
            }
        }
        //通过班级id查询学生Id
        List<Integer> studentIdList = classMapper.getStudentIdListByClassId(addExamUserDto.getClassId());
        for(Integer studentId:studentIdList){
            examMapper.addUserExam(studentId,addExamUserDto.getExamId());
        }


        return 1;
    }

    @Override
    public void publishExam(Integer examId) {
        // 1.修改考试状态为发布状态
        examMapper.updateExamStatus(examId, 1);

        // 2.查询考生 id 列表
        List<Integer> userIdList = examMapper.getExamUserIdList(examId);

        // 3.异步发送通知
        notificationService.sendExamNotifications(userIdList);
    }

    @Override
    public Integer getExamIdByPaperId(Integer paperId) {
        return examMapper.getExamIdByPaperId(paperId) ;
    }

    @Override
    public void updateExamStatus(Integer examId, Integer status) {
        //查询考试信息
        Exam exam=examMapper.getExamById(examId);
        LocalDateTime startTime=null;
        LocalDateTime endTime=null;

        if(status==2){
            exam.setStatus(status);
            startTime=LocalDateTime.now();
           endTime=exam.getStartTime().plusMinutes(exam.getExamDuration());
        }
        examMapper.updateExamMnultifileStatus(startTime,endTime,status,examId);
    }

    @Override
    public Integer joinExam(Integer examId) {
        //查看是否迟到
        Exam exam=examMapper.getExamById(examId);
        log.info("考试开始时间："+exam.getStartTime().plusMinutes(exam.getLimitEnterTime()));

        if(exam.getStartTime().plusMinutes(exam.getLimitEnterTime()).isBefore(LocalDateTime.now())){
            //迟到
            examMapper.updteExamUserStatus(examId,BaseContext.getCurrentId(),3);
            return -1;
        }
        //是否开始考试
        if(exam.getStartTime().isAfter(LocalDateTime.now())){
            return -2;
        }

        //修改考生状态
        examMapper.updteExamUserStatus(examId,BaseContext.getCurrentId(),1);
        return 1;

    }

    @Override
    public Result<ExamPaperDetailVo> getExamingPaperById(Integer examId) {

        ExamPaperDetailVo examPaperDetailVo=new ExamPaperDetailVo();
        //查询考试信息
        Exam exam=examMapper.getExamById(examId);
        BeanUtils.copyProperties (exam,examPaperDetailVo);
        //查询试卷信息
        PaperWithQuestionVo paperWithQuestionVo = paperMapper.getPaperWithQuestionVo(exam.getPaperId());
         //屏蔽答案
        for(QuestionVO questionVO:paperWithQuestionVo.getQuestions()){
            questionVO.setCorrectAnswer(" ");
        }
        if(exam.getCheatFlag()==0){
            //题目乱序
            List<QuestionVO> questionVOS=paperWithQuestionVo.getQuestions();
            for(int i=0;i<questionVOS.size();i++){
                int j= (int)(Math.random()*questionVOS.size());
                QuestionVO temp=questionVOS.get(i);
                questionVOS.set(i,questionVOS.get(j));
                questionVOS.set(j,temp);
            }
        }
        if(exam.getCheatFlag()==1){
            //选项乱序
            for(QuestionVO questionVO:paperWithQuestionVo.getQuestions()){
                List<OptionVO> optionVOS=questionVO.getOptions();
                for(int i=0;i<optionVOS.size();i++){
                    int j= (int)(Math.random()*optionVOS.size());
                    OptionVO temp=optionVOS.get(i);
                    optionVOS.set(i,optionVOS.get(j));
                    optionVOS.set(j,temp);
                }
            }
        }

         examPaperDetailVo.setPaperWithQuestionVo(paperWithQuestionVo);
        return Result.success(examPaperDetailVo);
    }

    public void processExamSubmission(SubmitExamDTO submitExamDTO) {
        submitExamDTO.setUserId(BaseContext.getCurrentId());

        // 将用户答案列表转换为 JSON 字符串
        String answersJson;
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            answersJson = objectMapper.writeValueAsString(submitExamDTO.getAnswers());
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to convert answers to JSON", e);
        }

        // 将 JSON 字符串直接设置到 submitExamDTO 中
        submitExamDTO.setAnswersJson(answersJson);

        // 调用 MyBatis Mapper 进行插入或更新操作
        examMapper.processExamSubmission(submitExamDTO);
    }


    @Override
    @Transactional
    public int markUnsubmittedExams() {
        return examMapper.updateUnsubmittedExams();
    }


    @Override
    public PageBean<ExamScoreVO> getUserExamScores(Integer userId, Integer page, Integer pageSize) {
        // 使用 PageHelper 分页
        PageHelper.startPage(page, pageSize);
        List<ExamScoreVO> examScores = userExamMapper.selectUserExamScores(userId);

        // 封装分页结果
        PageInfo<ExamScoreVO> pageInfo = new PageInfo<>(examScores);
        PageBean<ExamScoreVO> pageBean = new PageBean<>();
        pageBean.setTotal(pageInfo.getTotal());
        pageBean.setRows(pageInfo.getList());

        return pageBean;
    }

    @Override
    public Integer getExamStatus(Integer examId) {
        return  examMapper.getExamStatus(examId);
    }

    @Override
    public int countExamByUserId(Integer userId) {
        return  examMapper.countExamByUserId(userId);
    }


}
